/*
  以下为函数和闭包模式创建模块
  浏览器数据存储方式有以下：localstorage,sessionstorage,indexedDB（从存储时间，内存大小区分）
  indexDB优点是：存储容量大；支持异步操作；具有事务特点；
  indexDB缺点是：不支持DO操作；不能跨域
*/

export function Storage() {
  // TODO:window.indexedDB存储模型修改状态
  // @ts-ignore
  const indexedDB = window.indexedDB||window.webikitIndexedDB||window.mozIndexedDB||window.msIndexedDB;

  if (indexedDB === undefined) {
    console.warn("Storage: IndexedDB not available.");
    return {
      init: function () {},
      get: function () {},
      set: function () {},
      clear: function () {},
    };
  }

  const name = "threejs-editor";
  const version = 1;

  let database: any;

  return {
    init: function (callback: any) {
      const request = indexedDB.open(name, version);
      request.onupgradeneeded = function (event: any) {
        //创建一个新的数据库或者修改数据库版本号时触发
        const db = event.target.result;

        if (db.objectStoreNames.contains("states") === false) {
          db.createObjectStore("states");
        }
      };

      request.onsuccess = function (event: any) {
        database = event.target.result;

        callback();
      };

      request.onerror = function (event) {
        console.error("IndexedDB", event);
      };
    },

    get: function (callback: any) {
      //创建一个事务 || 创建一个事务，并要求具有读写权限
      const transaction = database.transaction(["states"], "readwrite");
      const objectStore = transaction.objectStore("states"); //获取对象仓库
      const request = objectStore.get(0);//获取数据 || getAll()获取全部数据
      request.onsuccess = function (event: any) {
        callback(event.target.result);
      };
    },

    set: function (data: any) {
      const start = performance.now();

      const transaction = database.transaction(["states"], "readwrite");
      const objectStore = transaction.objectStore("states");
      const request = objectStore.put(data, 0);
      request.onsuccess = function () {
        console.log(
          "[" + /\d\d\:\d\d\:\d\d/.exec(new Date() as any)?.[0] + "]",
          "Saved state to IndexedDB. " +
            (performance.now() - start).toFixed(2) +
            "ms"
        );
      };
    },

    clear: function () {
      if (database === undefined) return;

      const transaction = database.transaction(["states"], "readwrite");
      const objectStore = transaction.objectStore("states");
      const request = objectStore.clear();
      request.onsuccess = function () {
        console.log(
          "[" + /\d\d\:\d\d\:\d\d/.exec(new Date() as any)?.[0] + "]",
          "Cleared IndexedDB."
        );
      };
    },
  };
}
